﻿Imports System.ComponentModel
Imports System.Text
Imports System.Threading
Public Class BatteryPort : Inherits Transport

    Const GetCapacityPercent As String = ":001300000ee6~"
    Dim closing As Boolean = False

    <Description("电池电量")>
    Public ReadOnly Property Percent As UInteger

    <Description("串口名称")>
    Public Property ComName As String = "/dev/ttyS0"

    Public Sub Dispose()
        Close()
        closing = True
    End Sub

    Public Overloads Sub Begin()
        Console.WriteLine("Start Battery Port.")
        If Ready Then
            Console.WriteLine("Already Begin.")
            Return
        End If
        Task.Run(Sub()
                     While True
                         Begin(ComName, baudrate:=9600)
                         If closing Then
                             Return
                         End If
                         If Ready Then
                             Exit While
                         End If
                         Thread.Sleep(10000)
                     End While
                     Console.WriteLine("Open Port Succesfully, Start to Send Message.")
                     While True
                         If closing Then
                             Return
                         End If
                         GetPercent()
                         Thread.Sleep(30000)
                     End While
                     Console.WriteLine("Stop Reading Battery.")
                 End Sub
        )
    End Sub

    Public Function Parse(buf() As Byte) As Boolean
        Dim head = 0
        While True
            If buf(head) <> &H3A Then
                head += 1
                If head = buf.Length Then
                    Console.WriteLine("No Frame Head.")
                    Return False
                End If
            Else
                Exit While
            End If
        End While

        If buf(head + 3) = &H39 And buf(head + 4) = &H33 Then
            Dim percent(1) As Byte
            Array.Copy(buf, head + 11, percent, 0, 2)
            Dim str_val = Encoding.UTF8.GetString(percent)
            _Percent = Convert.ToUInt16(str_val, 16)
            Console.WriteLine($"{Now()} - Battery Percent: {Me.Percent}%")
        End If
        Return True
    End Function

    Public Sub GetPercent()
        For i = 0 To 3
            If SendMsg(GetCapacityPercent) Then
                Return
            End If
            '有时候要连发三次唤醒电池
            Thread.Sleep(1000)
        Next
    End Sub

    Public Function SendMsg(msg As String) As Boolean
        If Not Ready Then
            Console.WriteLine("Serial Port Not Open Yet.")
            Return False
        End If
        Dim buf(1023) As Byte
        Dim index = 0
        Dim timeout = False
        Dim t As New Timers.Timer(200) With
        {
            .AutoReset = False,
            .Enabled = True
        }
        AddHandler t.Elapsed, Sub()
                                  timeout = True
                              End Sub
        port.Write(msg)
        While True
            If port.BytesToRead > 0 Then
                buf(index) = port.ReadByte()
                If buf(index) = &H7E Then
                    Return Parse(buf)
                End If
                index += 1
                If index = 1024 Then
                    Console.WriteLine("Index Out of Bound.")
                    Return False
                End If
            End If
            If timeout Then
                Console.WriteLine("Wait Battery Ack Time Out.")
                Exit While
            End If
        End While
        Return False
    End Function

End Class
